为什么这个文件上传代码会破坏我的MP3文件?

时间:2016-02-24 06:30:26

标签: ruby file-upload upload sinatra

我有一个基于Sinatra的项目page,用户可以上传MP3文件。

<h2><%= I18n.t(:home_title) %></h2>
<%= I18n.t(:upload_body_text) %>
<form action="/<%= I18n.locale %>/upload" method="post" enctype="multipart/form-data">
<p>
<input type="file" name="song" size="40">
</p>
<div>
<input type="submit" value="<%= I18n.t(:home_submit) %>">
</div>
</form>

上传由此route处理:

post "/upload" do 
  File.open('uploads/' + params['song'][:filename], "w") do |f|
    f.write(params['song'][:tempfile].read)
  end
  erb :main
end

文件上传后,它已损坏:

  1. Windows Media Player中的MP3文件图像失真。
  2. 声音已损坏(听起来有误)。
  3. 我该如何解决?

1 个答案:

答案 0 :(得分:3)

您正在以文本模式打开文件(默认设置):

g  E ?  ? 8 º ? Ä ì  ß ê ( ? ½ ^ ~ ? ? X  ?

但你正在写二进制数据(MP3)。您需要在binary mode中打开目标文件:

import java.util.Scanner;
import java.util.Random;
public class Program4
{
public static void main(String[] args)
{
    if(args.length < 2)
    {
        usage();
    }
    else if(args[0].equals("-e"))
    {
        encrypt(args);
    }
    else if(args[0].equals("-d"))
    {
        decrypt(args);
    }

}   
        //Intro (Usage Method)
    public static void usage()
    {
        System.out.println("Stream Encryption program by my name");
        System.out.println("usage: java Encrypt [-e, -d] < inputFile > outputFile" );
    }
        //Encrypt Method
        public static void encrypt(String[] args)
    {   Scanner scan = new Scanner(System.in);
        String key1 = args[1];
        long key = Long.parseLong(key1);
        Random rng = new Random(key);
        int randomNum = rng.nextInt(256);
        while (scan.hasNextLine())
        {
            String s = scan.nextLine();
            for (int i = 0; i < s.length(); i++)
            {
                char allChars = s.charAt(i);
                int cipherNums = allChars ^ randomNum;
                System.out.print(cipherNums + " ");
            }

        }
    }   

        //Decrypt Method
        public static void decrypt(String[] args)
    {   String key1 = args[1];
        long key = Long.parseLong(key1);
        Random rng = new Random(key);
        Scanner scan = new Scanner(System.in);

            while (scan.hasNextInt())
        {
            int next = scan.nextInt();
            int randomNum = rng.nextInt(256);
            int decipher = next ^ randomNum;
            System.out.print((char)decipher + " ");

        }

    }

}

或IO库将尝试将EOL转换为Windows风格的CR-LF对:

File.open('uploads/' + params['song'][:filename], "w")

此外,您不应使用用户提供的名称("b" Binary file mode Suppresses EOL <-> CRLF conversion on Windows. And sets external encoding to ASCII-8BIT unless explicitly specified. )作为文件名而不彻底清除它;或者更好,不要使用他们的名字,将他们的名字存储在某个地方的数据库中,并使用表格的File.open('uploads/' + params['song'][:filename], "wb") # --------------------------------------------------^ 作为文件名。