app上传文件时,服务端如何接收文件?
发布于 8 年前 作者 JarvisQJ 9573 次浏览 来自 问答

百度出来的,还有github上的,一般都是适用于网页的。app怎么上传呢? 另外,如果是视频这种大文件呢?

15 回复

都是走http协议,具体实现我也不知道,百度可以找到

来自酷炫的 CNodeMD

@liygheart 适用于app的解决方案找不到啊

@qujinxiong 没有特殊需求,就是走http协议

来自酷炫的 CNodeMD

@qujinxiong

还有啥然后?

就是正常http post,请求content-type是multipart/form-data,http客户端可定都支持,服务器解析的时候安装part解析参数就完了

@TakWolf 什么叫安装part解析,我就是不知道app具体怎么传文件,服务端怎么接收。比如,post请求是用req.body接收,文件呢

客户端使用input file格式标签,google有File类可以查查api看看

@qujinxiong 你的客户端是什么语言实现的?

http post 通常情况传值,我们用的是 content-type : application/x-www-form-urlencoded,body格式是:a=1&b=2

还有一种格式叫做 multipart/form-data ,使用关键key分割body,可以上传较大数据(普通的参数传值,可以用,只不过没必要)

POST http://www.example.com HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA

------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="text"

title
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="file"; filename="chrome.png"
Content-Type: image/png

PNG ... content of chrome.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--

http客户端都支持这个格式,创建body的时候创建form-data格式的body就行。我不知道你客户端是什么语言实现的,但是通常http客户端都支持

################

服务端怎么解析?

node解析form-data请求body,通常需要中间件,例如 express 就需要 body-parser 中间件来解析form-data

########################

https://imququ.com/post/four-ways-to-post-data-in-http.html

nodeclub中接收图片文件的实现,你可以参考一下:https://github.com/cnodejs/nodeclub/blob/master/controllers/topic.js#L446

另外,如果是视频这种大文件呢?

你要上传的视频,平均多大呢? 通常情况上传文件,没有特殊需求,走http实现是最简单的

但是,如果你传的文件,大小是1个G,普通的http就不合适了,你可能要做些策略调整来实现断点、进度等更好的体验,具体实现另说

@TakWolf 客户端是app,也就是iOS和Android。视频一般不超300兆。我可以用网页和formidable实现上传,用app就不知道怎么上传数据、怎么接收数据?

@TakWolf var formidable = require(‘formidable’), http = require(‘http’), util = require(‘util’);

http.createServer(function(req, res) { if (req.url == ‘/upload’ && req.method.toLowerCase() == ‘post’) { // parse a file upload var form = new formidable.IncomingForm();

form.parse(req, function(err, fields, files) {
  res.writeHead(200, {'content-type': 'text/plain'});
  res.write('received upload:\n\n');
  res.end(util.inspect({fields: fields, files: files}));
});

return;

}

// show a file upload form res.writeHead(200, {‘content-type’: ‘text/html’}); res.end( ’<form action="/upload" enctype=“multipart/form-data” method=“post”>’+ ’<input type=“text” name=“title”><br>’+ ’<input type=“file” name=“upload” multiple=“multiple”><br>’+ ’<input type=“submit” value=“Upload”>’+ ’</form>’ ); }).listen(8080); 这是formidable的demo,给出的是web的实例,我希望知道app的话如何实现?

我之前用的是multer 上传 大文件不好说好用不 没传过

@qujinxiong 根据你给出的这一段:

<form action="/upload" enctype="multipart/form-data" method="post">
<input type="text" name="title">
<input type="file" name="upload" multiple="multiple">
<input type="submit" value="Upload">
</form>

提交地址为:/upload 请求的content-type为:multipart/form-data 提交了两个参数:title-> String upload->File


Android端对应的参考实现: 假设httpClient使用 OkHttp3

File file = {通过何种方式获取文件对象}
OkHttpClient httpClient = new OkHttpClient();

Request request = new Request.Builder()
        .url("/upload")
        .post(new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("title", "你的标题")
                .addFormDataPart("upload", file.getName(), RequestBody.create(MediaType.parse("*/*"), file))
                .build())
        .build();

Response response = httpClient.newCall(request).execute();
从这里开始处理你的响应

或者使用更优雅的 retrofit2

    @POST("/upload")
    @Multipart
    Call<Void> uploadFile(
            @Part MultipartBody.Part title,
            @Part MultipartBody.Part file
    );

    public static MultipartBody.Part stringMultipart(@NonNull String name, @NonNull String value) {
        return MultipartBody.Part.createFormData(name, value);
    }

    public static MultipartBody.Part fileMultipart(@NonNull String name, @NonNull File file) {
        return MultipartBody.Part.createFormData(name, file.getName(), RequestBody.create(MediaType.parse("*/*"), file));
    }
	
	service.uploadFile(stringMultipart("title", "你的标题"), fileMultipart("upload", file))..enqueue(new Call.....)
	

iOS端的实现原理类似

@TakWolf 非常感谢,原来你是“全贱”的。已经可以实现较大文件上传!

总结一下,虽然不知道app的同事如何获取文件对象和如何向服务端传递参数,但是我们通过formidable共同实现了demo。 啰嗦一下,结论是,formidable可以实现app的文件(包括图片和视频)上传

回到顶部