之前,就听过“跨域上传”图片的问题,只是疏于研究,也就一再搁置,直至今天再次遇见这个不能避免的“坑”,才不得不思考一下,怎么“跨域上传”图片或者文件?

问题来源:

何为“跨域”? ——就是给你一个接口,外面暴露的url(并非是自己项目中的url),然后你发post()请求,请求给你的接口,请求成功,接口就会返回给你想要的结果。

实际情况:

我们公司自己做的项目一般都是使用nodejs的thinkjs框架(ThinkJS 是一款使用 ES6/7 特性全新开发的 Node.js MVC 框架,使用 ES7 中 async/await,或者 ES6 中的 */yield 特性彻底解决了 Node.js 中异步嵌套的问题。)之前我们的上传图片都是显示在自己项目本地,而这次的需求却加上了请求另一个人的接口地址,然后正常上传图片。

页面HTML主要代码:

...
<label style="fmargin-top: 10px;width: 100px" ></label>
<div id="addImg">
<span class="addImglist"></span>
<img id="addPic" style="float: left;margin-top: 20px;margin-left: 20px" width="150px" height="100" src="/static/admin/img/addimg.jpg" onclick="addImg()">
</div>
<input type="file" name="uploadFile" id="fileupload_input" style="display: none"/> <div class="temp" style="float: left;margin-top: 20px;margin-left: 20px">
<img src="" class="showImg" ondblclick="canceImg(this)" width="150px" height="100"/>
<input type="hidden" class="imgs" name="imgs"/>
</div>
...
<script>
function addImg() {
uploadimg('dynamic');
} function uploadimg(type) {//这里的图片上传分为两种形式:动态以及用户头像
var url='';
if(type=='dynamic'){
url="/tools/uploadutils/uploadtonet?type=dynamic&t=" + new Date().getTime();//文件上传地址 请求接口地址
}else{
url="/article/article/upload?type=portrait&t=" + new Date().getTime();//文件上传地址
}
jQuery('#fileupload_input').click().fileupload({
dataType: 'json',
url: url,
done: function (e, result) {
if (result.result.errno==0) {
var data=result.result.data;
if(type=='dynamic'){
jQuery(".temp:first").clone().appendTo('#addImg .addImglist');
if(jQuery(".temp").length>=10){
jQuery("#addPic").hide();
}
jQuery('#addImg .showImg:last').attr("src",data.path);
jQuery('#addImg .imgs:last').val(data.savePath);
}else{
jQuery('#portrait').attr("src",imgsite+"/static"+data.path);
jQuery('#img').val(data.savePath)
}
} else {
jQuery.messager.alert('提示', "上传失败");
}
}
});
} function canceImg(me) {
jQuery(me).parent().remove();
if(jQuery(".temp").length<10){ //只能上传九张图
jQuery("#addPic").show();
}
}
</script>

后台项目中的js代码:

uploadutils.js(文件路径:/tools/uploadutils/的uploadtonet方法):

/**
* Created by *** on 2016/11/10
*/
'use strict'; import Base from '../base.js';
import imgutil from '../../../common/util/imgutil';
import fs from 'fs';
import request from 'request'; export default class extends Base {
/**
* 上传图片给前台接口(c#程序)
* @returns {Promise|*|void|PreventPromise}
*/
async uploadtonetAction() {
let type = this.get("type");
if (!think.isEmpty(this.file('uploadFile'))) {
let savePath = "";//保存在数据库的路径
let file = think.extend({}, this.file('uploadFile'));
let fPath = file.path;
let suffix = fPath.substr(fPath.lastIndexOf(".") + 1);
if (suffix == "jpg" || suffix == "png" || suffix == "jpeg") {
let apiBaseUrl = this.config("apiUrl");
let reqUrl = apiBaseUrl + "/upload.ashx"; //c#接口请求地址
let fileObj = imgutil.getCSharpImageUrl(this.param("type"), suffix);
let path = fileObj.path + fileObj.fileName;
let dbUri = "/" + path; //数据库保存的路径
let req = think.promisify(request.post);
let options = {
url: reqUrl,
method: "post",
formData: {
file: fs.createReadStream(fPath),
path: path
}
};
let res = await req(options);
let result = JSON.parse(res.body);
let imgUrl = this.config("apiImgsite") + dbUri; //回显的路径
if (result.status == 1) {//上传成功
savePath = result.data.join(',');
return this.success({
path: imgUrl,
savePath: savePath
});
} else {
return this.fail();
}
} else {
return this.fail("上传图片格式有误,请重新上传!");
}
}
} //跨域请求的方法
call = async function (url, fPath, path) {
let req = think.promisify(request.post);
let reqObj = {
url: url,
method: "post",
formData: {
file: fs.createReadStream(fPath),
path: path
}
};
return req(reqObj);
};
}

主要的问题出在哪里呢???其实主要知识点就是在下:

这段代码是老大给的,为此还被骂了一顿(这段代码很难理解吗?其实也不然,有时候就是觉得自己的脑子在代码运行方面实在不怎么灵光!明明自己知道的东西,因为粗心或者不自信总是犯错,导致一些不可挽回的“形象破坏”):

XMLHttpRequest Level 2添加了一个新的接口FormData.利用FormData对象,我们可以通过JavaScript用一些键值对来模拟一系列表单控件,我们还可以使用XMLHttpRequest的send()方法来异步的提交这个"表单".比起普通的ajax,使用FormData的最大优点就是我们可以异步上传一个二进制文件。(https://developer.mozilla.org/zh-CN/docs/Web/API/FormData)

在网上找到了一个C#实现http协议GET、POST请求 ,觉得挺好的    http://blog.chinaunix.net/uid-7552018-id-173395.html

const options = {
method: 'POST',
uri: testData.url + `uploadprofilephoto`,
formData: {
image: fs.createReadStream('/home/rje/photo.jpg')
}
};
const json: IResponse<string> = await request(options);

uri:就是要请求的图片上传地址;

formData:模拟表单提交,接口需要两个参数,一个文件路径,一个文件名,以键值对的形式传给它,最终便会返回给你想要的东西了。

只是在此项目中,使用await request(option)得不到接口返回的结果,于是只能使用thinkjs自带的 think.promisify()   —— think.promisify将一个异步函数自动改造,返回一个promise对象以供调用。

1.npm中request-promise模块(https://www.npmjs.com/package/request-promise),有具体的用法;

2.这次需求改动总结的小经验:

点击“添加图片”的时候,自动往后面添加一个相同的上传图片的点击框,即:

自己写的代码总是冗杂繁余,而其他人写的代码一看却是那么的简洁明了,不得不怀疑自己的能力。而自己想长期快乐的继续自己的这份工作时,就应该好好的沉淀自己,把自己培养成像同事一样的大神。

项目二(业务GO)——跨域上传图片(请求接口)的更多相关文章

  1. vue.js axios实现跨域http请求接口

    跨域post实例,用到了qs组件来避开ajax信使请求,并兼容Android. import axios from 'axios'; import qs from 'qs'; axios.post(' ...

  2. 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之十二 || 三种跨域方式比较,DTOs(数据传输对象)初探

    更新反馈 1.博友@落幕残情童鞋说到了,Nginx反向代理实现跨域,因为我目前还没有使用到,给忽略了,这次记录下,为下次补充.此坑已填 2.提示:跨域的姊妹篇——<三十三║ ⅖ 种方法实现完美跨 ...

  3. kindeditor4跨域上传图片解决

    项目中正在使用kindeditor, 版本号4.1.10 非常多公司的图片会走CDN,须要单独的一台图片上传服务如:(upload.268xue.com) kindeditor上传图片的简单内部流程: ...

  4. 跨域Ajax请求WebService方法

    一.允许跨域Ajax请求,更改如下配置: 在要调用的WebService上面添加特性标签: 二.以如下返回用户信息的WebService方法为例 三.在另一个网站上通过Ajax访问webService ...

  5. 【笔记】vue-cli 开发环境中跨域连接后台api(vue-resource 跨域post 请求)

    在vue-cli 项目中很多人会用到mock 数据(模拟数据),但是我觉得如果在真实的数据库交互中开发会更有安全感一些,所以查了一下百度很多人推荐的就是: 跨域! 跨域是什么概念?不同的主机名,同主机 ...

  6. ueditor富文本编辑器跨域上传图片解决办法

    在使用百度富文本编辑器上传图片的过程中,如果是有一台单独的图片服务器就需要将上传的图片放到图片服务器,比如在a.com的编辑器中上传图片,图片要保存到img.com,这就涉及到跨域上传图片,而在ued ...

  7. 【HTTP header】【Access-Control-Allow-Credentials】跨域Ajax请求时是否带Cookie的设置

    1. 无关Cookie跨域Ajax请求 客户端 以 Jquery 的 ajax 为例: $.ajax({ url : 'http://remote.domain.com/corsrequest', d ...

  8. 原创:【ajax | axios跨域简单请求+复杂请求】自定义header头Token请求Laravel5后台【亲测可用】

    如标题:我想在ajax的header头增加自定义Token进行跨域api认证并调用,api使用laravel5编写,如何实现? 首先,了解下CORS简单请求和复杂请求.  -- CORS简单请求 -- ...

  9. 跨域Ajax请求时是否带Cookie的设置

    1. 无关Cookie跨域Ajax请求 客户端 以 Jquery 的 ajax 为例: $.ajax({ url : 'http://remote.domain.com/corsrequest', d ...

随机推荐

  1. Java Servlet(五):GenericServlet与Servlet、HttpServlet之间的关系(jdk7+tomcat7+eclipse)

    本篇主要记录下,对GenericServlet的作用理解,及其与Servlet/HttpServlet之间的关系. 示例完成业务: 1.新建一个login.jsp页面,要求改页面能输入username ...

  2. js_css_dl.dt实现列表展开、折叠效果

    第一种方式:不提倡 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://w ...

  3. Android--Retrofit的简单使用(一)

    1,如果不太了解retrofit的同学可以先去官网学习一下简单使用:http://square.github.io/retrofit/,这里我们以一个简单的Get请求的例子来练习一下 2,https: ...

  4. XML 与 DataSet/DataTable 互相转换实例(C#)——转载

    // <summary>      /// XML形式的字符串.XML文江转换成DataSet.DataTable格式      /// </summary>      pub ...

  5. JAVA下的Thread.sleep方法一定要try

    try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } 不同于C#,JAVA里的Thre ...

  6. Auty自动化测试框架第二篇——读取与执行脚本列表

    [本文出自天外归云的博客园] 在Auty中的文件结构,lib目录下的read_selection.py和execute_selection.py文件:

  7. [poj2777] Count Color (线段树 + 位运算) (水题)

    发现自己越来越傻逼了.一道傻逼题搞了一晚上一直超时,凭啥子就我不能过??? 然后发现cin没关stdio同步... Description Chosen Problem Solving and Pro ...

  8. Java中request请求之 - 带文件上传的form表单

    常用系统开发中总免不了显示图片,保存一些文件资料等操作. 这些操作的背后,就是程序员最熟悉的 enctype="multipart/form-data"类型的表单. 说起file类 ...

  9. 关于分布式事务、两阶段提交、一阶段提交、Best Efforts 1PC模式和事务补偿机制的研究 转载

    1.XA XA是由X/Open组织提出的分布式事务的规范.XA规范主要定义了(全局)事务管理器(Transaction Manager)和(局部)资源管理器(Resource Manager)之间的接 ...

  10. 《BI那点儿事》数据仓库建模:星型模式、雪片模式

    数据仓库建模 — 星型模式Example of Star Schema 数据仓库建模 — 雪片模式Example of Snowflake Schema 节省存储空间 一定程度上的范式 星形 vs.雪 ...